package com.pagepub.core.tag.validate;

import java.net.URISyntaxException;
import java.net.URL;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.validator.Field;
import org.apache.commons.validator.Form;
import org.apache.commons.validator.Validator;
import org.apache.commons.validator.ValidatorAction;
import org.apache.commons.validator.ValidatorResources;
import org.apache.commons.validator.ValidatorResult;
import org.apache.commons.validator.ValidatorResults;
import org.apache.commons.validator.util.ValidatorUtils;

import com.pagepub.core.exception.ExceptionMessageParam;
import com.pagepub.core.exception.SysException;
import com.pagepub.core.utils.CalendarUtil;
import com.pagepub.core.utils.SystemCfgHelper;

/**
 * 使用org.apache.commons.validator版本是1.3
 * 验证框架入口实现
 * @author ggd 
 */
public class PortalValidatorUtil13Impl implements PortalValidatorUtil
{
	private static Log log = LogFactory.getLog(PortalValidatorUtil13Impl.class);

	private static ValidatorResources resources = null;
//	private static String requiredDate="requiredDate";

	static
	{
		initVR();// 初始化ValidatorResources
	}

	/**
	 * 检查vform表单
	 * @param vform
	 * @return 如果验证通不过则返回不等于null,否则返回null
	 * @throws  
	 * @throws MyFrameworkException 
	 */
	public Object check(Object vform, HttpServletRequest request)
	{
		ValidatorResults results = null;
		try
		{
			// 以包加类名作validation.xml中的form name
//			resources.getValidatorActions()
			
			Validator validator = new Validator(resources, vform.getClass().getName());
			validator.setParameter(Validator.BEAN_PARAM, vform);
			results = validator.validate();
			return validateResults(vform, results, resources, request);
		}
		catch (Exception e) 
		{
			log.error("PortalValidatorUtil13Impl.check("+vform+","+request+")出错!",e);
			ExceptionMessageParam emp=new ExceptionMessageParam();
			emp.setKeyOrMessageText("表单验证出错！");
			emp.setMessage(true);
//			try
//			{
				throw new SysException(emp,e);
//			}
//			catch (MyFrameworkException e1)
//			{
//				log.error("PortalValidatorUtil13Impl.check("+vform+","+request+")==>throw new MyFrameworkException("+emp+","+e+")出错!",e1);
//				return null;
//			}
		}
	}

	/**
	 * 初始化ValidatorResources validator-rules.xml和validation.xml配置文件放在class根目录下面

	 * 
	 * @param vr
	 */
	private static void initVR()
	{
		try
		{
			if (resources == null)
			{
				String[] cfgFileNames = SystemCfgHelper.getValitorCfgFileName().split(","); //getSystemCfgProps().getProperty(VALITOR_CFG_FILENAME_KEYNAME).split(",");
				String[] uris = new String[cfgFileNames.length];
				for (int i = 0; i < uris.length; i++)
				{
					URL url=PortalValidatorUtil13Impl.class.getResource(cfgFileNames[i]);
					try
					{
						uris[i] = url.toURI().toString();
					}
					catch (URISyntaxException e)
					{
						log.info("初始化validator-rules.xml和validation.xml配置文件指定URI有错不加载", e);
						continue;
					}
				}
				resources = new ValidatorResources(uris);
			}
		}
		catch (Exception e)
		{
			log.error("PortalValidatorUtil13Impl.initVR()初始化验证配置文件出错!",e);
			ExceptionMessageParam emp=new ExceptionMessageParam();
			emp.setKeyOrMessageText("初始化验证配置文件出错!");
			emp.setMessage(true);
			throw new SysException(emp,e);

		}
	}

	/**
	 * 验证vform中是否有不合法的数据
	 * 
	 * @param vform
	 * @param results
	 * @param resources
	 *            验出不合法的数据返回不为null，包含的值为
	 * @param request TODO
	 */
	private Set validateResults(Object vform, ValidatorResults results, ValidatorResources resources, HttpServletRequest request)
	{
		Form form = resources.getForm(Locale.getDefault(), vform.getClass().getName());// 取得配置文件中对应的form表单对象
		Set<PortalValidationMsg> errMsgSet = new HashSet<PortalValidationMsg>();
		Iterator propertyNames = results.getPropertyNames().iterator();
		while (propertyNames.hasNext())// 所有的验证字段集

		{
			String propertyName = (String) propertyNames.next();
			Field field = form.getField(propertyName);
			String msgArgs =SystemCfgHelper.getValidateFormPropertiesMsg(propertyName,vform.getClass().getName());//StringUtil.getLocalResourceStr(propertyName, VALIDATE_FORM_CFG_PROPERTIES_FILENAME);// 填充到validatorRulesMsg中{x}的参数

			if (msgArgs.length() == 0)
			{
				msgArgs = propertyName;// 如果忘记在validateFormCfg.properties配置，则取变量名称

			}
			ValidatorResult result = results.getValidatorResult(propertyName);

			Iterator keys = result.getActions();
			while (keys.hasNext())
			{
				String actName = (String) keys.next();
				
				if(request.getParameter(propertyName)==null)//防止没有在表单中的非String对象的非空验证过滤

				{
					break;
				}
				
				ValidatorAction action = resources.getValidatorAction(actName);
				if (!result.isValid(actName))// 某个方法验证通不过

				{
					Iterator fieldIt = field.getVars().keySet().iterator();
					while (fieldIt.hasNext())// 解析出错的错误信息，并取出所有参数具体的值

					{
						String varName = (String) fieldIt.next();// 变量参数名

						String varValue = field.getVarValue(varName);
						if (varValue.indexOf("$") == 0)// 在validatin.xml中设置动态变量的标志
						{
							String val = null;
							// 取得动态fieldName的值

							val = getValueAsString(vform, form.getField(varValue.substring(1)).getProperty());
							msgArgs += "," + (val != null ? val : "");
						}
						else
						{
							msgArgs += "," + varValue;
						}
					}
					PortalValidationMsg vm = new PortalValidationMsg();
					vm.setFieldName(propertyName);
					vm.setFieldKeyName(action.getMsg());
					vm.setFieldKeyArgs(msgArgs.split(","));
					errMsgSet.add(vm);// 把配置文件的错误信息key取出来放到set中，以便调用者调用

				}
			}
		}
		if(errMsgSet.size()==0)
		{
			return null;
		}
//		try
//		{
//			vform=vform.getClass().newInstance();//从重置表单对象这句很重要
//		}
//		catch (Exception e)
//		{
//			log.error("PortalValidatorUtil13Impl.validateResults()==>实例化"+vform.getClass().getName()+"出错!");
//			log.error(e);
//			ExceptionMessageParam emp=new ExceptionMessageParam();
//			emp.setKeyOrMessageText("PortalValidatorUtil13Impl.validateResults()==>实例化"+vform.getClass().getName()+"出错!");
//			emp.setMessage(true);
//			try
//			{
//				throw new MyFrameworkException(emp,e);
//			}
//			catch (MyFrameworkException e1)
//			{
//				e1.printStackTrace();
//			}
//		}
		return errMsgSet;
	}

	/**
	 * 取vform对象中的propertyName属性值，如果是日期类型转为格式化后的字串
	 * 
	 * @param vform
	 * @param propertyName
	 * @return
	 */
	private String getValueAsString(Object vform, String propertyName)
	{
		try
		{

			if (isDateType(vform, propertyName))
			{
				Object obj = null;
				try
				{
					obj = PropertyUtils.getNestedProperty(vform, propertyName);
				}
				catch (Exception e)
				{
					obj = vform.getClass().getMethod(
							"get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1)).invoke(
							vform);
				}
				return CalendarUtil.date2String((Date) obj, "yyyy-MM-dd");
			}
			else
			{
				return ValidatorUtils.getValueAsString(vform, propertyName);
			}
		}
		catch (Exception e)
		{
			log.error("PortalValidatorUtil13Impl.getValueAsString()==>"+vform.getClass().getName()+"找"+propertyName+"出错!",e);
			ExceptionMessageParam emp=new ExceptionMessageParam();
			emp.setKeyOrMessageText("PortalValidatorUtil13Impl.getValueAsString()==>"+vform.getClass().getName()+"找"+propertyName+"出错!");
			emp.setMessage(true);
			throw new SysException(emp,e);
//			try
//			{
//			}
//			catch (MyFrameworkException e1)
//			{
//				log.error("PortalValidatorUtil13Impl.getValueAsString()==>throw new MyFrameworkException(emp,e)",e1);
//				return null;
//			}
		}
	}

	/**
	 * 返回propertyName字段是否是日期类型包括util.date
	 * 
	 * @param vform
	 * @param propertyName
	 * @return
	 */
	private boolean isDateType(Object vform, String propertyName)
	{
		Object obj = null;
		try
		{
			obj = PropertyUtils.getNestedProperty(vform, propertyName);
			if (obj == null)
			{
				obj = PropertyUtils.getProperty(vform, propertyName);
			}
			if (obj instanceof Date)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		catch (Exception e)
		{
			log.error("PortalValidatorUtil13Impl.isDateType()日期转换错误!",e);
			ExceptionMessageParam emp=new ExceptionMessageParam();
			emp.setKeyOrMessageText("日期转换错误!");
			emp.setMessage(true);
			throw new SysException(emp,e);
//			try
//			{
//			}
//			catch (MyFrameworkException e1)
//			{
//				log.error("PortalValidatorUtil13Impl.isDateType()==>throw new MyFrameworkException(emp,e)",e1);
//				return false;
//			}
		}
	}

	public void test1()
	{
//		 TestForm tf=new TestForm();
//		 tf.setT1("t1ok");
//		<field property="schsName" depends="required"/>
//	      <field property="exeDepartment" depends="required"/>
//	      <field property="executePerson" depends="required"/>
//	      <field property="finacSchedule" depends="required"/>
//	      <field property="stepOrder" depends="intRang
//		 tf.setT2("");
//		SchemeStepForm ssf=new SchemeStepForm();
//		ssf.setSchsName("schsName");
//		ssf.setExeDepartment("");
//		ssf.setFinacSchedule("");
//		 tf.setInt2(new Integer(1000));
//		 tf.setStr3("3");
//		 tf.setStr1("1");
//		 tf.setDate1(new Date("2006/06/01"));
//		 tf.setDate3(new Date("2005/06/01"));
//		 System.out.println(check(ssf));
	}

	public static void main(String[] args)
	{
		 PortalValidatorUtil13Impl  my =new PortalValidatorUtil13Impl();
		 my.test1();
	}
}
